









<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>scale4j - 
        documentation</title>
    <link rel="stylesheet" href="./css/maven-theme.css" type="text/css" />
    <link rel="stylesheet" href="./css/maven-base.css" type="text/css"/>
    <link rel="stylesheet" href="./css/prettify.css" type="text/css"/>
    <link rel="stylesheet" href="./css/print.css" type="text/css" media="print" />
    <script type="text/javascript" src="./js/prettify.js"></script>
    <script type="text/javascript" src="./js/niftycube.js"></script>
    <script type="text/javascript">
        window.onload=function() {
            Nifty("div\#wrapper", "big");
            Nifty("div#breadcrumbs", "small");
            Nifty("div\#navcolumn", "small");
            Nifty("div.source", "medium");
            prettyPrint();
        }
    </script>
        <meta name="Date-Revision-yyyymmdd" content="20110326" />
      </head>
  <body>
    <div id="wrapper">
        <div id="banner">
                        <div id="bannerLeft">
    
                                            <img src="./images/scale4j.png" alt="$alt" />
    
            </div>
                            <div class="clear">
            <hr/>
          </div>
        </div>
        <div id="breadcrumbs">
              
  

  
    
            
  
    
                  <div class="xright">      
  

  
    
            
  
    
             <span id="publishDate">Last Published: 2011-03-26</span>
              &nbsp;| <span id="projectVersion">Version: 0.2</span>
            </div>
          <div class="clear">
            <hr/>
          </div>
        </div>
        <div id="leftColumn">
          <div id="navcolumn">
               
  

  
    
            
  
    
                       <h5>Overview</h5>
            <ul>
              
    <li class="none">
                    <a href="index.html">Description</a>
          </li>
              
    <li class="none">
                    <a href="tutorials.html">Tutorials</a>
          </li>
              
    <li class="none">
                    <a href="configuration.html">Configuration</a>
          </li>
              
    <li class="none">
              <strong>Documentation</strong>
        </li>
          </ul>
              <h5>Project Documentation</h5>
            <ul>
              
                
                    
                  
                  
                  
                  
              
        <li class="collapsed">
                    <a href="project-info.html">Project Information</a>
                </li>
              
                
                    
                  
                  
                  
                  
                  
                  
                  
                  
              
        <li class="collapsed">
                    <a href="project-reports.html">Project Reports</a>
                </li>
          </ul>
              <h5>External links</h5>
            <ul>
              
    <li class="none">
                    <a href="http://hazelcast.com" class="externalLink">hazelcast</a>
          </li>
              
    <li class="none">
                    <a href="http://www.springsource.org" class="externalLink">spring</a>
          </li>
              
    <li class="none">
                    <a href="http://www.hibernate.org" class="externalLink">hibernate</a>
          </li>
              
    <li class="none">
                    <a href="http://static.springsource.org/spring-batch" class="externalLink">spring batch</a>
          </li>
              
    <li class="none">
                    <a href="http://static.springsource.org/spring-security/site/index.html" class="externalLink">spring security</a>
          </li>
              
    <li class="none">
                    <a href="http://www.jboss.org/envers" class="externalLink">hibernate envers</a>
          </li>
              
    <li class="none">
                    <a href="http://www.hibernate.org/subprojects/search.html" class="externalLink">hibernate search</a>
          </li>
              
    <li class="none">
                    <a href="http://www.quartz-scheduler.org/" class="externalLink">quartz</a>
          </li>
              
    <li class="none">
                    <a href="http://www.atomikos.com/Publications/WebHome" class="externalLink">atomikos</a>
          </li>
              
    <li class="none">
                    <a href="http://perf4j.codehaus.org" class="externalLink">perf4j</a>
          </li>
              
    <li class="none">
                    <a href="http://vaadin.com/home" class="externalLink">vaadin</a>
          </li>
          </ul>
                                               <a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
            <img class="poweredBy"
                 alt="Built by Maven"
                 src="./images/logos/maven-feather.png"
                 width="90"
                 height="30"
                 border="1" />
          </a>
                           
  

  
    
            
  
    
            </div>
        </div>
        <div id="bodyColumn">
          <div id="contentBox">
            
    
        <div class="section"><h2>navigation<a name="navigation"></a></h2>
          <ul>
              <li><a href="#shared_classes">shared classes/utilities</a></li>
              <li><a href="#persistent_aspect">persistent aspect</a></li>
              <li><a href="#jpa2">jpa2 support</a></li>
              <li><a href="#clustering">clustering and data distributing</a></li>
              <li><a href="#quartz">quartz integration</a></li>
              <li><a href="#batch">spring batch integration</a></li>
              <li><a href="#jmx">jmx</a></li>
              <li><a href="#agent">agent</a></li>
              <li><a href="#web">web</a></li>
              <li><a href="#perf4j">real time performance statistic</a></li>
              <li><a href="#junit">unit/integration testing</a></li>
          </ul>
      </div>
        <a name="shared_classes"></a><div class="section"><h2 id="shared_classes">shared classes/utilities</h2>
            <p>
                You may find useful few common classes available in scale4j-share module.
            </p>
            <ul>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/RuntimeMode.html">com.katesoft.scale4j.common.RuntimeMode</a> - just enumeration with JUNIT/TEST/DEV/UAT/PROD values which corresponds to classical
                    environment definitions.
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/spring/RuntimePropertyPlaceholderConfigurer.html">com.katesoft.scale4j.common.spring.RuntimePropertyPlaceholderConfigurer</a> - enhanced property placeholder configurer,
                    clients should use this class instead of org.springframework.beans.factory.config.PropertyPlaceholderConfigurer</li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/spring/BeanPropertiesOverridePostProcessor.html">com.katesoft.scale4j.common.spring.BeanPropertiesOverridePostProcessor</a> - allows you to override any bean properties you need.
                    It is not recommended to use this class directly, use it for sub-classing.
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/services/IBeanNameReferences.html">com.katesoft.scale4j.common.services.IBeanNameReferences</a> - this interface contains bean names defined inside scale4j application,
                    it can be useful for autowiring(with @Qualifier annotation)
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/lang/OS.html">com.katesoft.scale4j.common.lang.OS</a> - enum for operation systems, most likely isWindows(), isLinux(), get()
                    methods can help you to identify target platform.
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/lang/RuntimeUtility.html">com.katesoft.scale4j.common.lang.RuntimeUtility</a> - contains number of utility methods and fields.<br />
                    Static fields
                     <ul>
                         <li><b>DATA_DIR</b> - basic data folder where logs/transaction manager's data/hibernate update scripts/hibernate search indexes are stored.</li>
                         <li><b>LOG_DATA_DIR</b> - folder where log files are stored</li>
                         <li><b>TM_DATA_DIR</b> - folder where transaction manager's data are stored</li>
                         <li><b>HIBERNATE_DATA_DIR</b> - folder where hibernate schema update scripts are stored</li>
                         <li><b>HIBERNATE_SEARCH_DATA_DIR</b> - folder where hibernate search indexes are stored</li>
                     </ul>
                    Static methods
                    <ul>
                        <li><b>gc</b> - force garbage collection. This method guarantees that garbage collection is done (unlike System.gc())</li>
                        <li><b>gcOnExit</b> - add shutdown hook which will perform garbage collection on JVM exit</li>
                        <li><b>runCommand</b> - runs external command in terminal (sh in unix/cmd in windows) and returns the command output</li>
                        <li><b>redirectStreams</b> - redirects given process's input and error streams to the specified streams</li>
                        <li><b>getRuntimeMode</b> - return actual runtime mode if java process was started with runtime_mode system property or NULL</li>
                    </ul>
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/common/jmx/JmxOperationInvoker.html">com.katesoft.scale4j.common.jmx.JmxOperationInvoker</a> - abstract class which allows you to execute jmx operation,
                    you would need to implement just actual actions.
                </li>
            </ul>
        </div>
        <a name="persistent_aspect"></a><div class="section"><h2 id="persistent_aspect">persistent aspect</h2>
            <p>
                Hibernate is great ORM framework which is used as persistent engine inside scale4j.
                Spring's transaction manager class is configured to be transaction manager for hibernate and all stuff around this consolidated in one spring configuration file.
                Most likely you would not want to change default configuration and would need just simple customization of hibernate session factory bean and datasource bean.
                It should not be a problem to do such customization as long as you have post processors for this.
            </p>
<div class="source"><pre>
  &lt;bean
      class=&quot;com.katesoft.scale4j.persistent.spring.postprocessor.HibernateSessionExtensionPostProcessor&quot;&gt;
    &lt;property name=&quot;annotatedClasses&quot;&gt;
      &lt;list&gt;
        &lt;value&gt;com.katesoft.scale4j.demo.domain.Currency&lt;/value&gt;
        &lt;value&gt;com.katesoft.scale4j.demo.domain.ExchangeRate&lt;/value&gt;
        ... any other domain classes
      &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name=&quot;beanProperties&quot;&gt;
      &lt;props&gt;
        &lt;prop key=&quot;schemaUpdate&quot;&gt;true&lt;/prop&gt;
        .. any other bean properties of AnnotationSessionFactoryBean class
      &lt;/props&gt;
    &lt;/property&gt;
    &lt;property name=&quot;hibernateProperties&quot;&gt;
      &lt;props&gt;
        &lt;prop key=&quot;hibernate.dialect&quot;&gt;org.hibernate.dialect.MySQL5InnoDBDialect&lt;/prop&gt;
        .. any other hibernate properties
      &lt;/props&gt;
    &lt;/property&gt;
  &lt;/bean&gt;

  &lt;bean class=&quot;com.katesoft.scale4j.persistent.spring.postprocessor.DatasourcePostProcessor&quot;&gt;
    &lt;property name=&quot;user&quot; value=&quot;xrates&quot;/&gt;
    &lt;property name=&quot;password&quot; value=&quot;xrates&quot;/&gt;
    &lt;property name=&quot;url&quot; value=&quot;jdbc:mysql://localhost/xrates&quot;/&gt;
    &lt;property name=&quot;driverClass&quot; value=&quot;com.mysql.jdbc.Driver&quot;/&gt;
  &lt;/bean&gt;</pre></div>

            <p>
                By the way instead of defining additional DatasourcePostProcessor post processor you can use <a href="./xref/com/katesoft/scale4j/common/spring/RuntimePropertyPlaceholderConfigurer.html">RuntimePropertyPlaceholderConfigurer</a>
                and set up overrides like
            </p>

<div class="source"><pre>
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/xrates
jdbc.username=xrates
jdbc.password=xrates
jdbc.initialSize=10
jdbc.maxActive=50
        </pre></div>

            <p>
                The same is applicable to hibernateProperties from HibernateSessionExtensionPostProcessor bean definition.
                You can add hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect to the properties frpm prev example.
                In the same way you can override schemaUpdate property just by setting property hibernate.schema.update=true.
                Hibernate session factory bean definition follows
            </p>
<div class="source"><pre>
&lt;bean id=&quot;jvmcluster.sessionFactory&quot;
      class=&quot;com.katesoft.scale4j.persistent.spring.LocalAnnotationSessionFactory&quot;
      p:namingStrategy-ref=&quot;jvmcluster.hibernate.namingStrategy&quot;
      p:dataSource-ref=&quot;jvmcluster.actual.datasource&quot;
      p:schemaUpdate=&quot;${hibernate.schema.update}&quot;
      p:exposeTransactionAwareSessionFactory=&quot;true&quot;
      p:useTransactionAwareDataSource=&quot;true&quot;&gt;
    &lt;property name=&quot;hibernateProperties&quot;&gt;
      &lt;value&gt;
        # Tooling
        hibernate.dialect=${hibernate.dialect}
        hibernate.bytecode.use_reflection_optimizer=true

        # Debugging
        hibernate.show_sql=${hibernate.show_sql}
        hibernate.format_sql=${hibernate.format_sql}
        hibernate.use_sql_comments=${hibernate.use_sql_comments}
        hibernate.generate_statistics=${hibernate.generate_statistics}

        #JDBC settings
        hibernate.jdbc.use_scrollable_resultset=true
        hibernate.jdbc.use_getGeneratedKeys=true
        hibernate.jdbc.batch_versioned_data=true
        hibernate.jdbc.use_streams_for_binary=true
      &lt;/value&gt;
    &lt;/property&gt;
    ..
  &lt;/bean&gt;
        </pre></div>

            <p>
                The same for datasource bean definition
            </p>
<div class="source"><pre>
&lt;bean id=&quot;jvmcluster.actual.datasource&quot;
      class=&quot;org.apache.commons.dbcp.BasicDataSource&quot;
      destroy-method=&quot;close&quot;
      p:defaultAutoCommit=&quot;false&quot;
      p:password=&quot;${jdbc.password}&quot;
      p:username=&quot;${jdbc.username}&quot;
      p:maxActive=&quot;${jdbc.maxActive}&quot;
      p:initialSize=&quot;${jdbc.initialSize}&quot;
      p:url=&quot;${jdbc.url}&quot;
      p:driverClassName=&quot;${jdbc.driverClassName}&quot;/&gt;
        </pre></div>

            <p>
                You can refer to pre-defined beans from you configuration using following self-explaining references:
                transactionManager,hibernateTemplate,datasource,jdbcTemplate,transactionTemplate,hibernateDaoSupport,sessionFactory
            </p>

            <p>
                Next step is to map your persistent entities. Nothing can be easier - just extend <a href="./xref/com/katesoft/scale4j/persistent/model/unified/AbstractPersistentEntity.html">AbstractPersistentEntity</a>.
                Lets examine class and start from fields:
                </p><ul>
                    <li>
                        <b>guid</b> - this is global unique identifier(type=string), which is actually UUID - populated in default constructor.
                        This may be useful for number of reasons - a lot of binding frameworks require unique identifier, for example graniteds framework.
                        You can use this identifier even if entity is not persisted yet.
                    </li>
                    <li>
                        <b>uniqueIdentifier</b> - this is actually unique identifier in scope of single table(type=long).
                        scale4j provides in-memory sequence generator, that is why you should not worry about populating this field.
                        Also this means that hibernate will not generate additional database queries.
                    </li>
                    <li>
                        <b>version</b> - hibernate optimistic version, also can be used as logical version of entity.
                    </li>
                </ul>
                Methods(getters/setters are not included):
                <ul>
                    <li>
                        <b>cleanBeanProperties</b> - setting to NULL all properties that were populated in default constructor, as result bean can be used
                        with hibernate's findByExample method.
                    </li>
                    <li>
                        <b>attributesLoaded</b> - returns true if this is actually bean and is not hibernate proxy.
                    </li>
                    <li>
                        <b>forceAttributesLoad</b> - causes initialization of hibernate proxy, clients can override this method to perform additional initialization
                        (for example initialize relations)
                    </li>
                    <li>
                        <b>reflectionToString</b> - prints state of entity using reflection.
                    </li>
                    <li>
                        <b>entityForUpdateCriteria</b> - creates detached criteria pre-populated with unique identifier, global unique identifier, and version.
                        You can then add additional restrictions using hibernate criteria API.
                    </li>
                    <li>
                        <b>entityForUpdateExample</b> - creates clone of entity and populates with unique identifier and version. clone can be used with findByExample method.
                    </li>
                    <li>
                        <b>getCreationTimestamp</b> -  looking for creation timestamp.
                        Please note that creation date is the revision's timestamp(first revision created by first insert statement), so this feature requires entity to be auditable.
                    </li>
                    <li>
                        <b>getLastModifyTimestamp</b> -  looking for last update timestamp.
                        Please note that last update timestamp is the revision's timestamp(latest revision created by latest update/insert statement), so this feature requires entity to be auditable.
                    </li>
                    <li>
                        <b>initializeProxy</b> - allows to init hibernate proxy. It is recommended to use this method instead of Hibernate.initializeProxy
                        because this method can init hibernate envers proxy as well(unlike Hibernate.initializeProxy).
                    </li>
                </ul>
            

            <p>
                It is time to examine how make our entities audit-able and search-able.
                Hibernate envers is great audit solution(which is not built on top of database triggers). Envers allows you to automatically create audit tables and persist
                entity revisions per create/update/delete operations and then use powerful audit query builder for historical data retrieving. The same for hibernate search - great framework built on top of
                apache lucene. Both libraries are configured, so you would not need to write event listeners.
                Lets consider simple self-explaining example(note usage of @Audited and @Indexed annotations) and visit
                <a class="externalLink" href="http://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/">hibernate search site</a> and
                <a class="externalLink" href="http://docs.jboss.org/hibernate/envers/3.6/reference/en-US/html_single/">hibernate envers site</a> for more details.
            </p>

<div class="source"><pre>
package com.katesoft.scale4j.web.model;

import com.katesoft.scale4j.persistent.model.unified.AbstractPersistentEntity;
import com.katesoft.scale4j.web.model.embedded.Account;
import com.katesoft.scale4j.web.model.embedded.Person;
import com.katesoft.scale4j.web.model.embedded.UserPreferences;
import org.hibernate.envers.Audited;
import org.hibernate.envers.NotAudited;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import org.hibernate.search.annotations.Store;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Classical implementation of User entity.
 *
 * @author kate2007
 */
@SuppressWarnings(&quot;serial&quot;)
@Entity
@Indexed
@Audited
@Table(name = &quot;t_user&quot;)
@Access(AccessType.FIELD)
@org.hibernate.annotations.Entity(dynamicUpdate = true, mutable = true)
@NamedQueries(value = {@NamedQuery(name = User.QUERY_FIND_BY_LOGIN,
                                   query = &quot;select u from User u where u.&quot; + User.PROP_LOGIN + &quot; = :username&quot;)})
public class User extends AbstractPersistentEntity implements UserDetails, CredentialsContainer
{
    // queries
    public static final String QUERY_FIND_BY_LOGIN = &quot;user.find_by_login&quot;;
    // properties
    public static final String PROP_LOGIN = &quot;login&quot;;
    public static final String PROP_EMAIL = &quot;email&quot;;
    // ***********************************************************************
    // ************************ persistent fields ****************************
    // ***********************************************************************
    @Column(name = &quot;login&quot;, unique = true, nullable = false, length = 100)
    @Field(index = Index.TOKENIZED, store = Store.NO)
    private String login;
    @NotAudited
    @Column(name = &quot;password&quot;, nullable = false, length = 255)
    private String password;
    @Column(name = &quot;e_mail&quot;, unique = true, length = 255)
    @Field(index = Index.TOKENIZED, store = Store.NO)
    private String email;
    @Column(name = &quot;open_id&quot;, length = 100)
    private String openId;
    @Embedded
    @IndexedEmbedded
    private Person person;
    @Embedded
    private Account account;
    @Embedded
    private UserPreferences userPreferences;
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = &quot;t_user_roles&quot;, joinColumns = @JoinColumn(name = &quot;user_id&quot;),
               inverseJoinColumns = @JoinColumn(name = &quot;role_id&quot;))
    private Set&lt;Role&gt; roles = new HashSet&lt;Role&gt;();
    // ***********************************************************************
    // ************************* (getters+setters) ***************************
    // ***********************************************************************

    public Person getPerson()
    {
        if (person == null) {
            person = new Person();
        }
        return person;
    }

    public Account getAccount()
    {
        if (account == null) {
            account = new Account();
        }
        return account;
    }

    public String getLogin()
    {
        return login;
    }

    public void setLogin(final String login)
    {
        this.login = login;
    }

    @Override
    public String getPassword()
    {
        return password;
    }

    public void setPassword(final String password)
    {
        this.password = password;
    }

    public String getEmail()
    {
        return email;
    }

    public void setEmail(final String EMail)
    {
        email = EMail;
    }

    public final String getOpenId()
    {
        return openId;
    }

    public final void setOpenId(final String openId)
    {
        this.openId = openId;
    }

    public Set&lt;Role&gt; getRoles()
    {
        if (roles == null) {
            roles = new HashSet&lt;Role&gt;();
        }
        return Collections.checkedSet(roles, Role.class);
    }

    public void setRoles(final Set&lt;Role&gt; roles)
    {
        this.roles = roles;
    }

    public UserPreferences getUserPreferences()
    {
        if (userPreferences == null) {
            userPreferences = new UserPreferences();
        }
        return userPreferences;
    }

    public void setUserPreferences(final UserPreferences userPreferences)
    {
        this.userPreferences = userPreferences;
    }
    // ================ spring security =========================

    @Override
    @Transient
    /**
     * @see org.springframework.security.userdetails.UserDetails#getAuthorities()
     * @return GrantedAuthority[] an array of roles.
     */
    public Collection&lt;GrantedAuthority&gt; getAuthorities()
    {
        final Set&lt;Role&gt; roles = getRoles();
        final Set&lt;GrantedAuthority&gt; authorities = new HashSet&lt;GrantedAuthority&gt;(roles.size());
        for (final Role role : roles) {
            authorities.add(new GrantedAuthorityImpl(role.getRole()));
        }
        return authorities;
    }

    @Transient
    @Override
    public String getUsername()
    {
        return getLogin();
    }

    @Transient
    @Override
    public boolean isAccountNonExpired()
    {
        return !getAccount().isAccountExpired();
    }

    @Transient
    @Override
    public boolean isAccountNonLocked()
    {
        return !getAccount().isAccountLocked();
    }

    @Transient
    @Override
    public boolean isCredentialsNonExpired()
    {
        return !getAccount().isCredentialsExpired();
    }

    @Transient
    @Override
    public boolean isEnabled()
    {
        return getAccount().isEnabled();
    }

    @Override
    public void eraseCredentials()
    {
        password = null;
    }
}</pre></div>

            <p>
                Now lets take a tour and watch few support classes <a href="./xref/com/katesoft/scale4j/persistent/client/LocalHibernateTemplate.html">LocalHibernateTemplate</a>
                and <a href="./xref/com/katesoft/scale4j/persistent/client/LocalHibernateDaoSupport.html">LocalHibernateDaoSupport</a> in action.
                LocalHibernateTemplate is actually sub-class of well-known HibernateTemplate class with some additional functionality:
            </p>
            <ul>
                <li>
                    <b>findEntityForUpdate</b> - looking for entity for update by unique identifier and comparing with expectedVersion - if actual version matches with expected,
                    then return found entity, else throw HibernateOptimisticLockingFailureException. It is very typical method functionality in multi-user application.
                    You will retrieve data and send both version and unique identifier - client after some time will send update version back that you can compare with original
                    and detect stale state.
                </li>
                <li>
                    <b>deleteAll</b> - delete all rows from database.
                </li>
                <li>
                    <b>loadByGlobalUniqueIdentifier</b> - looking for entity by global unique identifier.
                </li>
            </ul>

            <p>
                More interesting is to look into LocalHibernateDaoSupport functionality:
                </p><ul>
                    <li>
                        <b>latestRevision</b> - looking for the latest revision(revision number) of entity. Applicable only for audit-able entities.
                    </li>
                    <li>
                        <b>allRevisions</b> - retrieve all revision numbers of entity. Applicable only for audit-able entities.
                    </li>
                    <li>
                        <b>loadAllRevisions</b> - retrieve all revisions of entity. Applicable only for audit-able entities.
                    </li>
                    <li>
                        <b>latestRevisionForDate</b> - looking entity's historical data by given date(maximum date where date less or equals given). Applicable only for audit-able entities.
                    </li>
                    <li>
                        <b>search</b> - applicable only for search-able entities. Creates a fulltext query on top of a native Lucene query returning the matching objects.
                    </li>
                </ul>
            
        </div>

        <a name="jpa2"></a><div class="section"><h2 id="jpa2">JPA2 support</h2>
          <p>
            JPA 2 support is major feature of scale4j 0.2 <br />
            Previous version of scale4j didn't use hibernate's entity manager and used native Hibernate API(old school like AnnotationSessionFactory, HibernateTemplate, HibernateTransactionManager). <br />
            But now it is time to switch to JPA2 - but what about back compatibility? Does it mean that I can't use native hibernate any longer? <br />
            You would wonder - but it is just a matter or changing one property <b>scale4j.use.jpa</b> to true. Scale4j will change all other stuff for you -
            configure JpaTransactionManager, build entity manager using exactly the same configuration details etc. <br />
            Now your favorite <a href="./xref/com/katesoft/scale4j/persistent/client/LocalHibernateTemplate.html">LocalHibernateTemplate</a> implements both <b>org.springframework.orm.jpa.JpaOperations</b>
            and <b>org.springframework.orm.hibernate3.HibernateOperations</b>. <br />
            As of now pre-defined domain entities can be used with Type Safe criteria API which is the main feature of JPA2 so far.
            Lets move to concrete example and consider User example:
          </p>
<div class="source"><pre>
        final User entity = new User...;

        entity.getPerson().setFistName(&quot;first_name1&quot;);
        entity.getPerson().setSecondName(&quot;second_name1&quot;);
        entity.getPerson().setMiddleName(&quot;middle_name1&quot;);

        entity.getAccount().setAccountExpired(false);
        entity.getAccount().setAccountLocked(true);
        entity.getAccount().setCredentialsExpired(false);

        hibernateTemplate.save(entity);
        Role role = new Role();
        role.setRole(&quot;role1&quot;);
        hibernateTemplate.save(role);
        entity.getRoles().add(role);
        hibernateTemplate.update(entity);
</pre></div>
            <p>
                And query entity by role
            </p>
<div class="source"><pre>
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery&lt;User&gt; query = cb.createQuery(User.class);
        Root&lt;User&gt; root = query.from(User.class);
        SetJoin&lt;User, Role&gt; rolesJoin = root.join(User_.roles);
        query.where(cb.equal(rolesJoin.get(Role_.role), role), cb.equal(root.get(User_.uniqueIdentifier), entity.getUniqueIdentifier()),
                    cb.equal(root.get(User_.guid), entity.getGlobalUniqueIdentifier()));
</pre></div>
            <p>
                or by embedded classes
            </p>
<div class="source"><pre>
                final CriteriaBuilder cb = em.getCriteriaBuilder();
                CriteriaQuery&lt;User&gt; query = cb.createQuery(User.class);
                final Root&lt;User&gt; root = query.from(User.class);
                List&lt;Predicate&gt; conditions = new LinkedList&lt;Predicate&gt;()
                {
                    {
                        add(cb.equal(root.get(User_.uniqueIdentifier), entity.getUniqueIdentifier()));
                        add(cb.equal(root.get(User_.guid), entity.getGlobalUniqueIdentifier()));
                        add(cb.equal(root.get(User_.person).get(Person_.fistName), &quot;first_name1&quot;));
                        add(cb.equal(root.get(User_.person).get(Person_.secondName), &quot;second_name1&quot;));
                        add(cb.equal(root.get(User_.person).get(Person_.middleName), &quot;middle_name1&quot;));
                        add(cb.equal(root.get(User_.account).get(Account_.accountExpired), false));
                        add(cb.equal(root.get(User_.account).get(Account_.accountLocked), true));
                    }
                };
                query.where(conditions.toArray(new Predicate[conditions.size()]));
                User user = em.createQuery(query).getResultList().iterator().next();
</pre></div>
           <p>
               Last step is to configure automatic meta model generation and attach to maven build - <a class="externalLink" href="http://docs.jboss.org/hibernate/stable/jpamodelgen/reference/en-US/html_single/#maven-processor-plugin">Hibernate JPA 2 Metamodel Generator</a> .
           </p>
        </div>
        
        <a name="clustering"></a><div class="section"><h2 id="clustering">clustering and data distributing</h2>
            <p>
                scale4j-rttp(real time transaction processor) module is actual data distribution platform - provides fault tolerant capability as well as high scalability.
                Itself rttp is second level in-memory cache solution. It is highly recommended to use this module instead of scale4j-persistent module and ideally you should not depend
                on scale4j-persistent directly. So lets examine available features:
            </p>

            <ul>
                <li>
                    <b>Hazelcast integration</b> First and the most important question - why hazelcast(not terracotta, not oracle coherence, not oscache, not ehcache, not gigaspaces)? <br />
                    Hazelcast is an open source clustering and highly scalable data distribution platform for Java, which is:
                    <ul>
                        <li>Lightning-fast; thousands of operations/sec.</li>
                        <li>Fail-safe; no losing data after crashes.</li>
                        <li>Dynamically scales as new servers added.</li>
                        <li>Super-easy to use; include a single jar.</li>
                    </ul>
                    Hazelcast is pure Java. JVMs that are running Hazelcast will dynamically cluster.
                    Although by default Hazelcast will use multicast for discovery, it can also be configured to only use TCP/IP for environments where multicast is not available or preferred.

                    <p>
                       Hazelcast is extremely simple to use framework with unique user-friendly features like 'Distributed Executor Service', 'Distributed Locks', 'Cluster Monitoring Tool' and
                       'Distributed Data Structures' itself. So that is why we are using hazelcast.
                    </p>
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/rttp/jobs/DistributedTaskExecutor.html">DistributedTaskExecutor</a> - this class allows you to execute cluster-wide tasks execute your code in cluster.
                    You would simply pass Runnable or Callable. One important note - unsure you are passing java.io.Serializable task.
                    Implements org.springframework.core.task.TaskExecutor interface so can be used through Spring's TaskExecutor abstraction.
                    You can refer bean definition using <b>rttp.client.jobs.executor</b> ref or com.katesoft.scale4j.common.services.IBeanNameReferences.RTTP_CLIENT_SCHEDULER from code.
                </li>
                <li>
                    How can I inject HazelcastInstance? Simply by implementing <a href="./xref/com/katesoft/scale4j/rttp/client/IClusterInstanceAware.html">IClusterInstanceAware</a> or extending ClusterInstanceAwareBean.
                    Then you can operate with instance directly, but please do not call lifecycle methods.
                    DistributedTaskExecutor itself is implementation of IClusterInstanceAware interface.
                </li>
                <li>
                    There is consolidated spring configuration file located under classpath:META-INF/spring/simple-rttpContext.xml .
                </li>
                <li>
                    100% sure you would want to use your own hazelcast configuration file.
                    In this case you would need to pass <b>hazelcast_config</b> system property when starting you application.
                    Here is an example of custom config file
                    <div class="source"><pre>
&lt;hazelcast&gt;
  &lt;group&gt;
    &lt;name&gt;prod&lt;/name&gt;
    &lt;password&gt;prod-pass&lt;/password&gt;
  &lt;/group&gt;
  &lt;network&gt;
    &lt;port auto-increment=&quot;true&quot;&gt;5701&lt;/port&gt;
    &lt;join&gt;
      &lt;multicast enabled=&quot;true&quot;&gt;
        &lt;multicast-group&gt;224.2.2.3&lt;/multicast-group&gt;
        &lt;multicast-port&gt;54327&lt;/multicast-port&gt;
      &lt;/multicast&gt;
    &lt;/join&gt;
    &lt;symmetric-encryption enabled=&quot;true&quot;&gt;
      &lt;algorithm&gt;PBEWithMD5AndDES&lt;/algorithm&gt;
      &lt;salt&gt;jvmcluster%%#[092]salt&lt;/salt&gt;
      &lt;password&gt;$$jvmcluster$$pass$$&lt;/password&gt;
      &lt;iteration-count&gt;19&lt;/iteration-count&gt;
    &lt;/symmetric-encryption&gt;
  &lt;/network&gt;
  &lt;executor-service&gt;
    &lt;core-pool-size&gt;16&lt;/core-pool-size&gt;
    &lt;max-pool-size&gt;10000&lt;/max-pool-size&gt;
    &lt;keep-alive-seconds&gt;60&lt;/keep-alive-seconds&gt;
  &lt;/executor-service&gt;
  &lt;queue name=&quot;default&quot;&gt;
    &lt;!--
        Maximum size of the queue. When a JVM's local queue size reaches the maximum,
        all put/offer operations will get blocked until the queue size
        of the JVM goes down below the maximum.
        Any integer between 0 and Integer.MAX_VALUE. 0 means
        Integer.MAX_VALUE. Default is 0.
    --&gt;
    &lt;max-size-per-jvm&gt;10000000&lt;/max-size-per-jvm&gt;
    &lt;!--
        Maximum number of seconds for each item to stay in the queue. Items that are
        not consumed in &lt;time-to-live-seconds&gt; will automatically
        get evicted from the queue.
        Any integer between 0 and Integer.MAX_VALUE. 0 means
        infinite. Default is 0.
    --&gt;
    &lt;time-to-live-seconds&gt;0&lt;/time-to-live-seconds&gt;
  &lt;/queue&gt;
  &lt;map name=&quot;default&quot;&gt;
    &lt;!--
        Number of backups. If 1 is set as the backup-count for example,
        then all entries of the map will be copied to another JVM for
        fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
    --&gt;
    &lt;backup-count&gt;1&lt;/backup-count&gt;
    &lt;!--
        Valid values are:
        NONE (no eviction),
        LRU (Least Recently Used),
        LFU (Least Frequently Used).
        NONE is the default.
    --&gt;
    &lt;eviction-policy&gt;LRU&lt;/eviction-policy&gt;
    &lt;!--
        Maximum size of the map. When max size is reached,
        map is evicted based on the policy defined.
        Any integer between 0 and Integer.MAX_VALUE. 0 means
        Integer.MAX_VALUE. Default is 0.
    --&gt;
    &lt;max-size&gt;10000000&lt;/max-size&gt;
    &lt;!--
        When max. size is reached, specified percentage of
        the map will be evicted. Any integer between 0 and 100.
        If 25 is set for example, 25% of the entries will
        get evicted.
    --&gt;
    &lt;eviction-percentage&gt;25&lt;/eviction-percentage&gt;
  &lt;/map&gt;
&lt;/hazelcast&gt;</pre></div>
                </li>
            </ul>
        </div>

        <a name="quartz"></a><div class="section"><h2 id="quartz">quartz integration</h2>
            <p>
                Quartz is integrated into scale4j but actually declared as optional dependency so if you would like to use quartz lets add necessary dependency first
</p><div class="source"><pre>
    &lt;dependency&gt;
        &lt;groupId&gt;org.quartz-scheduler&lt;/groupId&gt;
        &lt;artifactId&gt;quartz&lt;/artifactId&gt;
        &lt;version&gt;1.8.4&lt;/version&gt;
        &lt;exclusions&gt;
          &lt;exclusion&gt;
            &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
            &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
          &lt;/exclusion&gt;
          &lt;exclusion&gt;
            &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
            &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
          &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;</pre></div>
            
            <p>
                Quartz configured to be a clustered by default. <br />
                Notes:
                </p><ul>
                    <li>importing consolidated jobs configuration file - just simply classpath:META-INF/spring/rttp-jobs-context.xml</li>
                    <li>self-explaining spring references - rttp.client.scheduler</li>
                    <li>configuration details/requirements - <a class="externalLink" href="http://www.quartz-scheduler.org/docs/1.x/configuration/ConfigJDBCJobStoreClustering.html">quartz cfg</a></li>
                    <li><b>one important note before usage</b> - Never run clustering on separate machines, unless their clocks are synchronized using some form
                        of time-sync service (daemon) that runs very regularly (the clocks must be within a second of each other).
                        See <a class="externalLink" href="http://www.boulder.nist.gov/timefreq/service/its.htm">http://www.boulder.nist.gov/timefreq/service/its.htm</a> if you are unfamiliar with how to do this.
                    </li>
                    <li>
                        <b>quartz schema creation</b> - scale4j will take care for creating quartz database tables according to your database type, but
                        you may want to disable this feature and create tables by hand. To do so jut override property <b>rttp.scheduler.db.create=false</b>.
                        You can use <a href="./xref/com/katesoft/scale4j/common/spring/RuntimePropertyPlaceholderConfigurer.html">RuntimePropertyPlaceholderConfigurer</a> for properties override.
                    </li>
                    <li>
                        scheduler bean definition
<div class="source"><pre>
&lt;bean id=&quot;rttp.scheduler.executor&quot;
      class=&quot;org.springframework.scheduling.quartz.SimpleThreadPoolTaskExecutor&quot;
      p:threadNamePrefix=&quot;rttp.client.local.executor&quot;
      p:makeThreadsDaemons=&quot;false&quot;
      p:threadCount=&quot;${rttp.quartz.scheduler.max.threads}&quot;
      p:waitForJobsToCompleteOnShutdown=&quot;false&quot;/&gt;
  &lt;bean id=&quot;rttp.client.scheduler&quot;
      class=&quot;com.katesoft.scale4j.rttp.jobs.LocalSchedulerFactoryBean&quot;
      p:waitForJobsToCompleteOnShutdown=&quot;false&quot;
      p:taskExecutor-ref=&quot;rttp.scheduler.executor&quot;
      p:dataSource-ref=&quot;jvmcluster.actual.datasource&quot;
      p:transactionManager-ref=&quot;jvmcluster.jdbcTransactionManager&quot;
      p:autoStartup=&quot;${rttp.scheduler.auto.start}&quot;
      depends-on=&quot;rttp.db.initializer&quot;&gt;
    &lt;property name=&quot;quartzProperties&quot;&gt;
      &lt;props&gt;
        &lt;prop key=&quot;org.quartz.jobStore.tablePrefix&quot;&gt;${rttp.quartz.tables.prefix}&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.scheduler.instanceName&quot;&gt;rttp_scheduler&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.scheduler.instanceId&quot;&gt;AUTO&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.scheduler.instanceIdGenerator.class&quot;&gt;com.katesoft.scale4j.rttp.jobs.RttpSchedulerInstanceIdGenerator&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.scheduler.skipUpdateCheck&quot;&gt;true&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.plugin.shutdownhook.class&quot;&gt;org.quartz.plugins.management.ShutdownHookPlugin&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.plugin.shutdownhook.cleanShutdown&quot;&gt;false&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.jobStore.isClustered&quot;&gt;true&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.jobStore.clusterCheckinInterval&quot;&gt;5000&lt;/prop&gt;
        &lt;prop key=&quot;org.quartz.scheduler.jmx.export&quot;&gt;true&lt;/prop&gt;
      &lt;/props&gt;
    &lt;/property&gt;
  &lt;/bean&gt;</pre></div>
                    </li>
                    <li>
                        <a href="./xref/com/katesoft/scale4j/rttp/jobs/SchedulerJobsRegistrator.html">SchedulerJobsRegistrator</a> - this class allows you to register your jobs/triggers.
                        You can specify list of job details and list of triggers manually or use default 'autoDetected' feature.
                        Also you can register calendars/schedulerListeners/globalJobListeners/jobListeners/globalTriggerListeners/triggerListeners.
                    </li>
                </ul>
            
        </div>

        <a name="batch"></a><div class="section"><h2 id="batch">spring batch integration</h2>
            <p>
                Spring batch is integrated into scale4j but actually declared as optional dependency so if you would like to use pring batch lets add necessary dependency first
</p><div class="source"><pre>
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.batch&lt;/groupId&gt;
        &lt;artifactId&gt;spring-batch-core&lt;/artifactId&gt;
        &lt;version&gt;2.1.7.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;</pre></div>
            
            <p>
                Notes:
                </p><ul>
                    <li>importing consolidated jobs configuration file - just simply classpath:META-INF/spring/rttp-batch-context.xml</li>
                    <li>self-explaining spring references - jobExplorer, jobLauncher, jobOperator, jobRegistry, jobRepository</li>
                    <li>
                        <b>batch schema creation</b> - scale4j will take care for creating batch database tables according to your database type, but
                        you may want to disable this feature and create tables by hand. To do so jut override property <b>rttp.batch.db.create=false</b>.
                        You can use <a href="./xref/com/katesoft/scale4j/common/spring/RuntimePropertyPlaceholderConfigurer.html">RuntimePropertyPlaceholderConfigurer</a> for properties override.
                    </li>
                    <li>
                        Please visit  <a class="externalLink" href="http://static.springsource.org/spring-batch/reference/html-single/index.html#metaDataSchema">spring batch meta data page</a> and read
                        'recommendations for indexing meta data tables' section carefully.
                    </li>
                    <li>
                        batch bean definitions
<div class="source"><pre>
&lt;bean id=&quot;rttp.job.repository&quot;
      class=&quot;org.springframework.batch.core.repository.support.JobRepositoryFactoryBean&quot;
      p:transactionManager-ref=&quot;jvmcluster.jdbcTransactionManager&quot;
      p:dataSource-ref=&quot;jvmcluster.actual.datasource&quot;
      p:tablePrefix=&quot;${rttp.batch.tables.prefix}&quot;
      p:isolationLevelForCreate=&quot;ISOLATION_READ_COMMITTED&quot;
      depends-on=&quot;rttp.db.initializer,jvmcluster.sessionFactory&quot;/&gt;
  &lt;bean
      class=&quot;com.katesoft.scale4j.rttp.jobs.jdbc.init.RttpBatchSchemaCreator&quot;
      p:rttpHazelcastBridge-ref=&quot;rttp.bridge&quot;
      p:sessionFactory-ref=&quot;&amp;amp;jvmcluster.sessionFactory&quot;
      p:tablesPrefix=&quot;${rttp.batch.tables.prefix}&quot;/&gt;
  &lt;bean
      id=&quot;rttp.job.launcher&quot;
      class=&quot;org.springframework.batch.core.launch.support.SimpleJobLauncher&quot;
      p:jobRepository-ref=&quot;rttp.job.repository&quot;/&gt;
  &lt;bean
      id=&quot;rttp.job.explorer&quot;
      class=&quot;org.springframework.batch.core.explore.support.JobExplorerFactoryBean&quot;
      p:dataSource-ref=&quot;jvmcluster.actual.datasource&quot;/&gt;
  &lt;bean
      id=&quot;rttp.job.registry&quot;
      class=&quot;org.springframework.batch.core.configuration.support.MapJobRegistry&quot;/&gt;
  &lt;bean
      id=&quot;rttp.job.operator&quot;
      class=&quot;org.springframework.batch.core.launch.support.SimpleJobOperator&quot;
      p:jobExplorer-ref=&quot;rttp.job.explorer&quot;
      p:jobRepository-ref=&quot;rttp.job.repository&quot;
      p:jobRegistry-ref=&quot;rttp.job.registry&quot;
      p:jobLauncher-ref=&quot;rttp.job.launcher&quot;/&gt;
  &lt;bean
      id=&quot;rttp.job.repository.post.processor&quot;
      class=&quot;org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor&quot;
      p:jobRegistry-ref=&quot;rttp.job.registry&quot;/&gt;

  &lt;alias name=&quot;rttp.job.explorer&quot; alias=&quot;jobExplorer&quot;/&gt;
  &lt;alias name=&quot;rttp.job.launcher&quot; alias=&quot;jobLauncher&quot;/&gt;
  &lt;alias name=&quot;rttp.job.operator&quot; alias=&quot;jobOperator&quot;/&gt;
  &lt;alias name=&quot;rttp.job.registry&quot; alias=&quot;jobRegistry&quot;/&gt;
  &lt;alias name=&quot;rttp.job.repository&quot; alias=&quot;jobRepository&quot;/&gt;
        </pre></div>
                    </li>
                    <li>
                        <a href="./xref/com/katesoft/scale4j/rttp/jobs/CrushedJobsCleaner.html">CrushedJobsCleaner</a> - this class can be used to 'clean-up crashed jobs' during spring context initialization.
                        What does it mean - 'crashed job'? It is possible that particular spring batch job execution started and didn't finish correctly(for example because OutOfMemoryError occurred).
                        This job execution will not be cleaned automatically during startup, however this class will update endTime to current timestamp and set status=FAILED.
                        You can specify list of jobs to be cleaned or set cleanAll=true (all failed job executions to be cleaned).
                    </li>
                    <li>
                        <a href="./xref/com/katesoft/scale4j/rttp/jobs/tasklets/CacheCleanTasklet.html">CacheCleanTasklet</a> - this class can be used to clear domain entities cache.
                        Actually it is even tasklet designed to be used within spring batch which will call <b>isCleanable()</b> method on each entity from cache.
                        If result of invocation is true then entity will be removed from cache. It is recommended to override default implementation and add some sanity business logic.
                    </li>
                    <li>
                        Spring batch itself is not scheduler o care should be taken for integration.
                        scale4j provides 2 classes which will do necessary integration work <a href="./xref/com/katesoft/scale4j/rttp/jobs/SpringBatchJobLauncher.html">SpringBatchJobLauncher</a>
                        and <a href="./xref/com/katesoft/scale4j/rttp/jobs/RttpJobDetailBean.html">RttpJobDetailBean</a>.
                    </li>
                    <li>
                        simple example of quartz+spring batch usage
<div class="source"><pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans:beans xmlns=&quot;http://www.springframework.org/schema/batch&quot;
    xmlns:beans=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns:p=&quot;http://www.springframework.org/schema/p&quot;
    xsi:schemaLocation=&quot;
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/batch
           http://www.springframework.org/schema/batch/spring-batch-2.1.xsd&quot;&gt;
  &lt;beans:import resource=&quot;classpath*:META-INF/spring/currencies-app-context.xml&quot;/&gt;
  &lt;beans:import resource=&quot;classpath*:META-INF/spring/rttp-jobs-context.xml&quot;/&gt;
  &lt;beans:import resource=&quot;classpath*:META-INF/spring/rttp-batch-context.xml&quot;/&gt;

  &lt;job id=&quot;intraday.job&quot; job-repository=&quot;jobRepository&quot;&gt;
    &lt;step id=&quot;intraday.step1&quot; next=&quot;intraday.step2&quot;&gt;
      &lt;tasklet ref=&quot;available.currencies.tasklet&quot;/&gt;
    &lt;/step&gt;
    &lt;step id=&quot;intraday.step2&quot;&gt;
      &lt;tasklet ref=&quot;currency.exchange.rates.tasklet&quot;/&gt;
    &lt;/step&gt;
  &lt;/job&gt;

  &lt;job id=&quot;eod.job&quot; job-repository=&quot;jobRepository&quot;&gt;
    &lt;step id=&quot;eod.step1&quot; next=&quot;eod.step2&quot;&gt;
      &lt;tasklet ref=&quot;available.currencies.tasklet&quot;/&gt;
    &lt;/step&gt;
    &lt;step id=&quot;eod.step2&quot;&gt;
      &lt;tasklet ref=&quot;currency.exchange.rates.tasklet&quot;/&gt;
    &lt;/step&gt;
  &lt;/job&gt;

  &lt;beans:bean
      class=&quot;com.katesoft.scale4j.rttp.jobs.SchedulerJobsRegistrator&quot;
      p:autoDetectJobs=&quot;true&quot;/&gt;

  &lt;beans:bean
      id=&quot;intraday.trigger&quot;
      class=&quot;org.springframework.scheduling.quartz.SimpleTriggerBean&quot;
      p:repeatInterval=&quot;300000&quot;
      p:jobDetail-ref=&quot;intraday.job.details&quot;/&gt;

  &lt;beans:bean
      id=&quot;eod.trigger&quot;
      class=&quot;org.springframework.scheduling.quartz.CronTriggerBean&quot;
      p:cronExpression=&quot;0 0 23 * * ?&quot;
      p:jobDetail-ref=&quot;eod.job.details&quot;/&gt;

  &lt;beans:bean
      id=&quot;eod.job.details&quot;
      class=&quot;com.katesoft.scale4j.rttp.jobs.RttpJobDetailBean&quot;
      p:group=&quot;scale4j-demo-group&quot;
      p:name=&quot;[end of day] job&quot;
      p:jobClass=&quot;com.katesoft.scale4j.rttp.jobs.SpringBatchJobLauncher&quot;
      p:job-ref=&quot;eod.job&quot;/&gt;

  &lt;beans:bean
      id=&quot;intraday.job.details&quot;
      class=&quot;com.katesoft.scale4j.rttp.jobs.RttpJobDetailBean&quot;
      p:group=&quot;scale4j-demo-group&quot;
      p:name=&quot;[x-rates-update] job&quot;
      p:jobClass=&quot;com.katesoft.scale4j.rttp.jobs.SpringBatchJobLauncher&quot;
      p:job-ref=&quot;intraday.job&quot;/&gt;
&lt;/beans:beans&gt;</pre></div>
                    </li>
                </ul>
            
        </div>

        <a name="jmx"></a><div class="section"><h2 id="jmx">JMX</h2>
            <p>
                scale4j provided built-in functionality for JMX beans exposing. Actually you would not need to import additional configuration, all you need to do
                is to add @ManagedResource annotation to your bean class.
                Please visit <a class="externalLink" href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jmx.html#jmx-interface-metadata">Using Source-Level Metadata (JDK 5.0 annotations)</a>
                to find out more details. You may want to look into jmx configuration around this
            </p>
<div class="source"><pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns:p=&quot;http://www.springframework.org/schema/p&quot;
       xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&quot;&gt;
  &lt;bean id=&quot;jvmcluster.mbean.server&quot;
      class=&quot;org.springframework.jmx.support.MBeanServerFactoryBean&quot;
      p:locateExistingServerIfPossible=&quot;true&quot;/&gt;
  &lt;bean id=&quot;jvmcluster.jmx.attributeSource&quot;
      class=&quot;org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource&quot;/&gt;
  &lt;bean id=&quot;jvmcluster.jmx.assembler&quot;
      class=&quot;org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler&quot;
      p:attributeSource-ref=&quot;jvmcluster.jmx.attributeSource&quot;/&gt;
  &lt;bean id=&quot;jvmcluster.jmx.namingStrategy&quot;
      class=&quot;org.springframework.jmx.export.naming.MetadataNamingStrategy&quot;
      p:attributeSource-ref=&quot;jvmcluster.jmx.attributeSource&quot;/&gt;
&lt;/beans&gt;</pre></div>
        </div>

        <a name="agent"></a><div class="section"><h2 id="agent">agent</h2>
            <p>
                scale4j-agent supports concept of services and is responsible for launching dedicated JVM for each of services.
                All background work is done for you(like JavaProcessBuilder abstraction, ServiceLauncher and few other).
                You would be able to manage lifecycle of services through JMX using JConsole.
                We would need to write configuration file for our services and pass this file to <a href="./xref/com/katesoft/scale4j/agent/Agent.html">Agent</a> class.
                Simplest way for us would be examine self-explaining config
            </p>
<div class="source"><pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;applicationConfiguration
    xmlns=&quot;http://katesoft.com/xml/jvmcluster&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://katesoft.com/xml/jvmcluster&quot;
    jmxPort=&quot;10774&quot;&gt;

  &lt;service name=&quot;service1&quot; mainClass=&quot;com.katesoft.scale4j.agent.SpringConfigurationRunner&quot; jmxPort=&quot;10775&quot;&gt;
    &lt;jvmConfiguration vmType=&quot;server&quot;&gt;
      &lt;memoryConfiguration initialHeap=&quot;32&quot; maxHeap=&quot;128&quot;/&gt;
      &lt;debugConfiguration port=&quot;11775&quot; debugSuspend=&quot;false&quot;/&gt;
      &lt;jvmArg value=&quot;-XX:+UseBiasedLocking&quot;/&gt;
    &lt;/jvmConfiguration&gt;
    &lt;logConfiguration location=&quot;log4j/log4j.xml&quot;/&gt;
    &lt;applicationArg value=&quot;META-INF/spring/jobs-service-container.xml&quot;/&gt;
  &lt;/service&gt;

  &lt;service name=&quot;service2&quot; mainClass=&quot;com.katesoft.scale4j.agent.SpringConfigurationRunner&quot; jmxPort=&quot;10776&quot;&gt;
    &lt;jvmConfiguration vmType=&quot;server&quot;&gt;
      &lt;memoryConfiguration initialHeap=&quot;32&quot; maxHeap=&quot;128&quot;/&gt;
      &lt;debugConfiguration port=&quot;11776&quot; debugSuspend=&quot;false&quot;/&gt;
      &lt;jvmArg value=&quot;-XX:-UseSpinning&quot;/&gt;
    &lt;/jvmConfiguration&gt;
    &lt;logConfiguration location=&quot;log4j/log4j.xml&quot;/&gt;
    &lt;applicationArg value=&quot;META-INF/spring/webapp-service-container.xml&quot;/&gt;
  &lt;/service&gt;

  &lt;globalConfiguration&gt;
    &lt;jvmArg value=&quot;-XX:-UseParallelGC&quot;/&gt;
    &lt;jvmArg value=&quot;-XX:+OptimizeStringConcat&quot;/&gt;

    &lt;systemProperty name=&quot;file.encoding&quot; value=&quot;UTF-8&quot;/&gt;
    &lt;systemProperty name=&quot;com.sun.management.jmxremote.authenticate&quot; value=&quot;false&quot;/&gt;
    &lt;systemProperty name=&quot;com.sun.management.jmxremote.ssl&quot; value=&quot;false&quot;/&gt;
  &lt;/globalConfiguration&gt;
&lt;/applicationConfiguration&gt;</pre></div>
            <p>
                We defined 2 services and assigned unique identifier to each of them(service1, service2).<br />
				Also we specified <a href="./xref/com/katesoft/scale4j/agent/SpringConfigurationRunner.html">SpringConfigurationRunner</a> as main class.<br />
				We need to specify jmx port for each of services(10775 for first service and 10776 for second service) - this allows agent to close spring application context
				in a safe way using remote JMX call. The same required for agent itself - 10774 port is used in our example. Now you can connect to both agent/services
				using jconsole with remote jmx connection details(localhost:10774, localhost:10775 and localhost:10776). <br />
				We configured memory for each of services (initialHeap=&quot;32&quot; maxHeap=&quot;128&quot;), specified log4j configuration file, and passed debug port.<br />
				Now we can easily debug our remote applications using remote localhost:11775 and localhost:11776 connections from favorite IDE.<br />
				SpringConfigurationRunner expects configuration locations as application arguments, so we added applicationArg=META-INF/spring/jobs-service-container.xml for first service
				and applicationArg=META-INF/spring/webapp-service-container.xml for second. <br />
                You can specify jvm argument on service level as well as on global configuration level(-XX:-UseParallelGC and -XX:+OptimizeStringConcat options propagated on both service,
				unlike -XX:+UseBiasedLocking which is defined for first service only). The same is applicable for systemProperty(we disabled jmx authentication by setting com.sun.management.jmxremote.authenticate to false
				and com.sun.management.jmxremote.ssl to false).
            </p>

            <p>
                Please take a look into xsd schema details <a href="./xsd/appConfiguration.html">xsd schema</a>. <br />
                The only one remaining step is to start/stop Agent class itself - the simplest way is to use maven exec plugin.
            </p>
<div class="source"><pre>
&lt;profiles&gt;
    &lt;profile&gt;
      &lt;id&gt;run&lt;/id&gt;
      &lt;build&gt;
        &lt;plugins&gt;
          &lt;plugin&gt;
            &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
            &lt;artifactId&gt;exec-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;1.2&lt;/version&gt;
            &lt;configuration&gt;
              &lt;executable&gt;java&lt;/executable&gt;
              &lt;arguments&gt;
                &lt;argument&gt;-Dcom.sun.management.jmxremote&lt;/argument&gt;
                &lt;argument&gt;-Dcom.sun.management.jmxremote.port=10774&lt;/argument&gt;
                &lt;argument&gt;-Dcom.sun.management.jmxremote.authenticate=false&lt;/argument&gt;
                &lt;argument&gt;-Dcom.sun.management.jmxremote.ssl=false&lt;/argument&gt;
                &lt;argument&gt;-Xms8m&lt;/argument&gt;
                &lt;argument&gt;-Xmx16m&lt;/argument&gt;
                &lt;argument&gt;-classpath&lt;/argument&gt;
                &lt;classpath/&gt;
                &lt;argument&gt;com.katesoft.scale4j.agent.Agent&lt;/argument&gt;
              &lt;/arguments&gt;
            &lt;/configuration&gt;
          &lt;/plugin&gt;
        &lt;/plugins&gt;
      &lt;/build&gt;
    &lt;/profile&gt;
    &lt;profile&gt;
      &lt;id&gt;stop&lt;/id&gt;
      &lt;build&gt;
        &lt;plugins&gt;
          &lt;plugin&gt;
            &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
            &lt;artifactId&gt;exec-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;1.2&lt;/version&gt;
            &lt;configuration&gt;
              &lt;executable&gt;java&lt;/executable&gt;
              &lt;arguments&gt;
                &lt;argument&gt;-Xms8m&lt;/argument&gt;
                &lt;argument&gt;-Xmx16m&lt;/argument&gt;
                &lt;argument&gt;-classpath&lt;/argument&gt;
                &lt;classpath/&gt;
                &lt;argument&gt;com.katesoft.scale4j.agent.Agent&lt;/argument&gt;
                &lt;argument&gt;-s&lt;/argument&gt;
              &lt;/arguments&gt;
            &lt;/configuration&gt;
          &lt;/plugin&gt;
        &lt;/plugins&gt;
      &lt;/build&gt;
    &lt;/profile&gt;
  &lt;/profiles&gt;</pre></div>

            <p>
                Available options of Agent class:
                </p><ul>
                    <li>-l</li> log4j configuration file location
                    <li>-c</li> location of appConfiguration.xml file location(actually appConfiguration.xml is default, you may override)
                    <li>-k</li> stop agent and destroy all services immediately(like kill -9, but from java)
                    <li>-s</li> stop agent and stop all services in a safe way
                </ul>
                Also there are few useful method available through JMX(rttp.agent node)
                <ul>
                    <li>isServiceRunning</li> check is service is running
                    <li>serviceStatus</li> retrieve status of service(STARTING/RUNNING/FAILED_TO_START/TERMINATED)
                    <li>serviceConfiguration</li> xml fragment of service configuration
                    <li>allServices</li> list of all services
                    <li>allServicesByStatus</li> list of all services and statuses(format service=status)
                    <li>stopService</li> stop service
                    <li>stop</li> stop agent itself and all services as well
                    <li>startService</li> start service (if not running already)
                </ul>
                You can re-start particular service without affecting all other.
            
        </div>

        <a name="web"></a><div class="section"><h2 id="web">web</h2>
            <p>
                scale4j-web module is actually additional functionality designed to be used within web applications.
                scale4j-web provides classical implementation of User/Role domain entities ready to work with spring security.
                But more important thing that you can find here is WebMonitor class which is jetty server itself enriched
                with per4j runtime statistic browser, log4j configurator, and very powerful hazelcast web console. <br />
                Notes:
            </p>
            <ul>
                <li>
                    <a href="./xref/com/katesoft/scale4j/web/model/User.html">User</a> - implementation of org.springframework.security.core.userdetails.UserDetails interface.
                    This class is audit-able and search-able and marked as Cachable(read-write cache).
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/web/model/Role.html">Role</a> - implementation of org.springframework.security.core.GrantedAuthority interface.
                    This class is audit-able and search-able and marked as Cachable(read-write cache).
                </li>
                <li>
                    <a href="./xref/com/katesoft/scale4j/web/webconsole/WebMonitor.html">WebMonitor</a> - jetty server which provides additional functionality for
                    runtime log4j configuration, per4f statistic browsing, and hazelcast cluster monitoring.
                    You can customize default context path(/), default log4j context path(/log4j), default per4j context path(/perf4j), and change default hazelcast monitor path(/hazelcast). <br />
                    One important note - you would need to specify war location of hazelcast-monitor application. It can be done by adding dependency
<div class="source"><pre>
&lt;dependency&gt;
      &lt;groupId&gt;com.hazelcast&lt;/groupId&gt;
      &lt;artifactId&gt;hazelcast-monitor&lt;/artifactId&gt;
      &lt;version&gt;1.9.2.2&lt;/version&gt;
      &lt;type&gt;war&lt;/type&gt;
      &lt;optional&gt;true&lt;/optional&gt;
    &lt;/dependency&gt;</pre></div>
                    and then define <b>hazelcastPathLocation</b>=${settings.localRepository}/com/hazelcast/hazelcast-monitor/1.9.2.2/hazelcast-monitor-1.9.2.2.war as location.<br />
                    As result you spring configuration file may looks like
<div class="source"><pre>
&lt;beans:bean
      id=&quot;web.monitor&quot;
      class=&quot;com.katesoft.scale4j.web.webconsole.WebMonitor&quot;&gt;
    &lt;beans:property name=&quot;connectors&quot;&gt;
      &lt;beans:list&gt;
        &lt;beans:bean class=&quot;org.mortbay.jetty.nio.SelectChannelConnector&quot;&gt;
          &lt;beans:property name=&quot;port&quot; value=&quot;8967&quot;/&gt;
        &lt;/beans:bean&gt;
      &lt;/beans:list&gt;
    &lt;/beans:property&gt;
    &lt;beans:property name=&quot;hazelcastWarLocation&quot; value=&quot;${hazelcastPathLocation}&quot;/&gt;
  &lt;/beans:bean&gt;</pre></div>
                </li>
            </ul>
        </div>
        
        <a name="perf4j"></a><div class="section"><h2 id="perf4j">real time performance statistic</h2>
            <p>
                scale4j provides basic capabilities for runtime statistic gathering. perf4j framework is used for this purpose.
                It is very easy to start using performance profiling - just add @Profiled annotation.
                <a href="./xref/com/katesoft/scale4j/persistent/client/LocalHibernateTemplate.html">LocalHibernateTemplate</a> itself uses per4j.
                Here is usage example
            </p>
<div class="source"><pre>
    @Override
    @Profiled(tag = &quot;hibernate.deleteAll_{$0.name}&quot;,
              message = &quot;deleteAll called with parameters[class={$0.name}]&quot;)
    public void deleteAll(final Class&lt;?&gt; clazz)
    {
        execute(new HibernateCallback&lt;Object&gt;()
        {
            @Override
            public Object doInHibernate(Session session) throws HibernateException
            {
                for (Object next : session.createCriteria(clazz).list()) {
                    session.delete(next);
                }
                session.flush();
                return null;
            }
        });
    }</pre></div>
            <p>
                One of the main benefits of Perf4J is that it allows performance analysis and monitoring on live production applications through extensions to common logging frameworks - log4j.
                Please visit <a class="externalLink" href="http://perf4j.codehaus.org/devguide.html#Using_the_log4j_Appenders_to_Generate_Real-Time_Performance_Information">Using the log4j Appenders to Generate Real-Time Performance Information</a> page
                and consider next example
            </p>
<div class="source"><pre>
&lt;appender name=&quot;graphExecutionTimes&quot;
      class=&quot;com.katesoft.scale4j.log.ChartStatisticsAppender&quot;&gt;
    &lt;param name=&quot;GraphType&quot; value=&quot;Mean&quot;/&gt;
    &lt;appender-ref ref=&quot;graphsFileAppender&quot;/&gt;
  &lt;/appender&gt;

  &lt;appender name=&quot;graphExecutionTPS&quot; class=&quot;com.katesoft.scale4j.log.ChartStatisticsAppender&quot;&gt;
    &lt;param name=&quot;GraphType&quot; value=&quot;TPS&quot;/&gt;
    &lt;appender-ref ref=&quot;graphsFileAppender&quot;/&gt;
  &lt;/appender&gt;

  &lt;appender name=&quot;perf4jFileAppender&quot; class=&quot;com.katesoft.scale4j.log.LogDataDirAwareFileAppender&quot;&gt;
    &lt;param name=&quot;File&quot; value=&quot;${service_id}-perfStats.log&quot;/&gt;
    &lt;layout class=&quot;org.apache.log4j.PatternLayout&quot;&gt;
      &lt;param name=&quot;ConversionPattern&quot; value=&quot;%m%n&quot;/&gt;
    &lt;/layout&gt;
  &lt;/appender&gt;

  &lt;appender name=&quot;graphsFileAppender&quot; class=&quot;com.katesoft.scale4j.log.LogDataDirAwareFileAppender&quot;&gt;
    &lt;param name=&quot;File&quot; value=&quot;${service_id}-perfGraphs.log&quot;/&gt;
    &lt;layout class=&quot;org.apache.log4j.PatternLayout&quot;&gt;
      &lt;param name=&quot;ConversionPattern&quot; value=&quot;%m%n&quot;/&gt;
    &lt;/layout&gt;
  &lt;/appender&gt;

  &lt;appender name=&quot;CoalescingStatistics&quot; class=&quot;org.perf4j.log4j.AsyncCoalescingStatisticsAppender&quot;&gt;
    &lt;param name=&quot;TimeSlice&quot; value=&quot;10000&quot;/&gt;
    &lt;appender-ref ref=&quot;perf4jFileAppender&quot;/&gt;
    &lt;appender-ref ref=&quot;graphExecutionTimes&quot;/&gt;
    &lt;appender-ref ref=&quot;graphExecutionTPS&quot;/&gt;
  &lt;/appender&gt;

  &lt;logger name=&quot;org.perf4j.TimingLogger&quot; additivity=&quot;false&quot;&gt;
    &lt;appender-ref ref=&quot;CoalescingStatistics&quot;/&gt;
  &lt;/logger&gt;</pre></div>
        </div>

        <a name="junit"></a><div class="section"><h2 id="junit">unit/integration testing</h2>
            <p>
                You can use <a href="./xref-test/com/katesoft/scale4j/persistent/context/AbstractPersistentTest.html">AbstractPersistentTest</a> for spring integration testing.
                This class does not include any specific spring locations, just defines common properties ready for spring auto-wiring.
                Here is real example of how you can create parent class for integration testing
            </p>
<div class="source"><pre>
package com.katesoft.scale4j.rttp.context;

import com.katesoft.scale4j.common.services.IBeanNameReferences;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

/** @author kate2007 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({&quot;/META-INF/spring/simple-rttpContext.xml&quot;,
                       &quot;/META-INF/spring/jvmcluster.rttp$postprocessing.xml&quot;,
                       &quot;/META-INF/spring/rttp-jobs-context.xml&quot;,
                       &quot;/META-INF/spring/rttp-batch-context.xml&quot;,
                       &quot;/META-INF/spring/jvmcluster-batch-junit.xml&quot;})
@TransactionConfiguration(defaultRollback = true,
                          transactionManager = IBeanNameReferences.TRANSACTION_MANAGER)
@Transactional
@DirtiesContext
public abstract class AbstractSimpleContextRTTPTest extends AbstractPersistentTest
{
    @Autowired
    protected HibernateTransactionManager hibernateTransactionManager;
}
</pre></div>
        </div>
    

          </div>
        </div>
        <div class="clear">
          <hr/>
        </div>
        <div id="footer">
          <div class="xright">Copyright &#169;          
   
          2010-2011
    
                    <a href="http://mykate-soft.com">mykate-soft</a>.
            All Rights Reserved.    
  

  
    
            
  
    
  </div>
          <div class="clear">
            <hr/>
          </div>
        </div>
    </div>
  </body>
</html>
